package com.whfc.fim.queue;

import com.alibaba.fastjson.JSON;
import com.whfc.common.constant.QueueConst;
import com.whfc.common.enums.AppWarnModuleType;
import com.whfc.common.exception.BizException;
import com.whfc.common.util.DateUtil;
import com.whfc.common.util.JSONUtil;
import com.whfc.entity.dto.msg.AppMsgToUserDTO;
import com.whfc.entity.dto.msg.PushMsgDTO;
import com.whfc.fim.dao.FimWarnFreqConfigMapper;
import com.whfc.fim.dto.FimMsgToUserDTO;
import com.whfc.fim.dto.FimResultWarnDTO;
import com.whfc.fim.dto.WarnCacheDTO;
import com.whfc.fim.entity.FimWarnFreqConfig;
import com.whfc.fim.manager.FimResultManager;
import com.whfc.fim.param.FimAlgResultParam;
import com.whfc.fim.redis.FimWarnRecordRedisDao;
import com.whfc.fuum.dto.SysAlgorithmTypeDTO;
import com.whfc.fuum.service.SysAlgorithmService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author : qzexing
 * @version : 1.0
 * @date : 2020/6/11 9:40
 */
@Component
@RabbitListener(queues = QueueConst.FIM_RESULT)
public class FimResultQueueMessageListener {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 报警默认值
     */
    private static final Integer DEFAULT_FREQUENCY_LIMIT_INTERVAL = 1;

    private static final String CONTENT = "%s在%s,监测到%s,请您及时处理";

    private static final String KEY = "fim-warn::{0}::{1}::{2}";


    @Autowired
    private FimResultManager fimResultManager;

    @Autowired
    private FimWarnRecordRedisDao warnRecordRedisDao;

    @Autowired
    private FimWarnFreqConfigMapper warnFreqConfigMapper;

    @DubboReference
    private SysAlgorithmService sysAlgorithmService;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @RabbitHandler
    public void process(String msg) {
        FimAlgResultParam fimAlgResultParam = JSON.parseObject(msg, FimAlgResultParam.class);
        try {
            logger.info("智能监控识别记录 msg:{}", msg);
            FimResultWarnDTO fimResultWarnDTO = fimResultManager.uploadAlgResult(fimAlgResultParam);
            Integer resultId = fimResultWarnDTO.getResultId();
            Integer deptId = fimResultWarnDTO.getDeptId();
            Integer algCheckType = fimResultWarnDTO.getAlgCheckType();
            Date time = fimResultWarnDTO.getTime();
            Integer deviceId = fimResultWarnDTO.getDeviceId();
            String deviceName = fimAlgResultParam.getDeviceName();
            List<FimMsgToUserDTO> userDtoList = fimResultWarnDTO.getUserDtoList();
            List<Integer> msgChannelList = fimResultWarnDTO.getMsgChannelList();
            //报警
            boolean frequency = checkWarnFrequency(algCheckType, deptId, deviceId, time);
            logger.info("报警规则===========================》{}，{}，{}，{}，{}",frequency,algCheckType,deptId,deviceId,time);
            if (frequency) {
                // 生成报警消息
                List<AppMsgToUserDTO> list = transferData(userDtoList);
                this.generateMessage(fimAlgResultParam.getAlgCheckTypeName(),resultId, deptId, deviceName, algCheckType, time, list, msgChannelList);
            }
        } catch (BizException e) {
            logger.error("业务处理失败: deviceId:{}, deviceName:{}", fimAlgResultParam.getDeviceId(), fimAlgResultParam.getDeviceName(), e);
        } catch (Exception e) {
            logger.error("同步报警记录出错.", e);
        }
    }

    /**
     * 转换消息接收人
     *
     * @param userDtoList 消息接收人
     * @return 消息接收人
     */
    private List<AppMsgToUserDTO> transferData(List<FimMsgToUserDTO> userDtoList) {
        List<AppMsgToUserDTO> list = new ArrayList<>();
        if (userDtoList == null || userDtoList.isEmpty()) {
            return list;
        }
        for (FimMsgToUserDTO fimMsgToUserDTO : userDtoList) {
            AppMsgToUserDTO appMsgToUserDTO = new AppMsgToUserDTO();
            appMsgToUserDTO.setDeptId(fimMsgToUserDTO.getDeptId());
            appMsgToUserDTO.setDeptName(fimMsgToUserDTO.getDeptName());
            appMsgToUserDTO.setUserId(fimMsgToUserDTO.getUserId());
            appMsgToUserDTO.setUsername(fimMsgToUserDTO.getUsername());
            appMsgToUserDTO.setNickName(fimMsgToUserDTO.getNickName());
            appMsgToUserDTO.setPhone(fimMsgToUserDTO.getPhone());
            appMsgToUserDTO.setRuleId(fimMsgToUserDTO.getRuleId());
            list.add(appMsgToUserDTO);
        }
        return list;
    }

    /**
     * 生成报警消息
     *
     * @param resultId     记录ID
     * @param deptId       组织机构ID
     * @param deviceName   设备名称
     * @param algCheckType 报警类型
     * @param time         触发时间
     */
    private void generateMessage(String algCheckTypeName,
                                 Integer resultId,
                                 Integer deptId,
                                 String deviceName,
                                 Integer algCheckType,
                                 Date time,
                                 List<AppMsgToUserDTO> userDtoList,
                                 List<Integer> msgChannelList) {
        String content = String.format(CONTENT, deviceName, DateUtil.formatDateTime(time), algCheckTypeName);

        PushMsgDTO msgDTO = new PushMsgDTO();
        msgDTO.setDeptId(deptId);
        msgDTO.setModuleType(AppWarnModuleType.FIM.value());
        msgDTO.setTime(time);
        msgDTO.setMsgObjectId(String.valueOf(resultId));
        msgDTO.setTitle(algCheckTypeName);
        msgDTO.setContent(content);
        msgDTO.setToUserList(userDtoList);
        msgDTO.setMsgChannelList(msgChannelList);
        logger.info("发送推送消息数据====》start {}",msgDTO.toString());
        amqpTemplate.convertAndSend(QueueConst.PUSH_MSG_EXCHANGE, "", JSONUtil.toString(msgDTO));
    }

    /**
     * 生成消息频率
     *
     * @param ruleType    规则类型
     * @param deptId      组织机构ID
     * @param deviceId    设备ID
     * @param triggerTime 触发时间
     * @return 是否生成消息
     */
    private boolean checkWarnFrequency(Integer ruleType, Integer deptId, Integer deviceId, Date triggerTime) {
        String dateStr = DateUtil.formatDate(new Date(), "yyyyMMdd");
        WarnCacheDTO machWarnRecord = warnRecordRedisDao.getWarnRecord(MessageFormat.format(KEY, dateStr, ruleType, deviceId));
        WarnCacheDTO warnCacheDTO = new WarnCacheDTO();
        if (machWarnRecord == null) {
            warnCacheDTO.setTime(triggerTime);
            warnRecordRedisDao.setWarnRecord(MessageFormat.format(KEY, dateStr, ruleType, deviceId), warnCacheDTO);
            return true;
        } else {
            Date time = machWarnRecord.getTime();
            Integer frequencyLimitInterval = 0;
            FimWarnFreqConfig warnFreqConfig = warnFreqConfigMapper.selectByDeptId(deptId);
            // 设置默认值
            if (warnFreqConfig == null) {
                frequencyLimitInterval = DEFAULT_FREQUENCY_LIMIT_INTERVAL;
            }
            // 不限制
            else if (warnFreqConfig.getFrequencyLimitInterval() == -1) {
                return true;
            }
            // 禁止
            else if (warnFreqConfig.getFrequencyLimitInterval() == 0) {
                return false;
            }
            //自定义值
            else {
                frequencyLimitInterval = warnFreqConfig.getFrequencyLimitInterval();
            }

            if (DateUtil.addMinutes(time, frequencyLimitInterval).before(triggerTime)) {
                warnCacheDTO.setTime(triggerTime);
                warnRecordRedisDao.setWarnRecord(MessageFormat.format(KEY, dateStr, ruleType, deviceId), warnCacheDTO);
                return true;
            }
            return false;
        }
    }

}
